package top.cptr.so.tripartiteqqlogin;


import com.alibaba.fastjson2.JSON;
import lombok.Data;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import top.cptr.so.tripartiteqqlogin.nanotation.NoParamFiled;
import top.cptr.so.tripartiteqqlogin.nanotation.ParamFiled;
import top.cptr.so.tripartiteqqlogin.paramter.OAuthPublicParam;
import top.cptr.so.tripartiteqqlogin.paramter.OpenIdRequestsParam;
import top.cptr.so.tripartiteqqlogin.paramter.OpenIdRequestsParam.OpenIdResponse;
import top.cptr.so.tripartiteqqlogin.paramter.TokenRequestParam;
import top.cptr.so.tripartiteqqlogin.paramter.TokenRequestParam.TokenResponse;
import top.cptr.so.tripartiteqqlogin.paramter.UserInfoRequestParam.UserInfoResponse;
import top.cptr.so.tripartiteqqlogin.utils.ObjectToURIParam;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;


/**
 * @author Tiger_L
 * QQ登录api主类
 */
@Data
public class QQLogin {
    //  授权类型，此值固定为“code”(必须)
    @ParamFiled(name = "response_type")
    private String responseType = "code";
    // 申请QQ登录成功后，分配给应用的appid。(必须)
    @ParamFiled(name = "client_id")
    private String clientId;
    // 分配给网站的appkey
    @NoParamFiled
    @ParamFiled(name = "client_secret")
    private String clientSecret;
    // 功授权后的回调地址，必须是注册appid时填写的主域名下的地址，建议设置为网站首页或网站的用户中心。注意需要将url进行URLEncode。(必须)
    @ParamFiled(name = "redirect_uri")
    private String redirectUri;
    // client端的状态值。(必须)
    private String state;
    // 请求用户授权时向用户显示的可进行授权的列表。(可选)
    private String scope;
    // 用于展示的样式  (可选)
    private String display;


    /**
     * 生成页面重定向地址
     *
     * @return qq登录地址
     */
    public String createLoginUrl() {
        StringBuilder loginUrl = new StringBuilder(QQApiUrl.AUTHORIZE);
        String uriParam = ObjectToURIParam.toURIParam(this);
        loginUrl.append(uriParam);
        return loginUrl.toString();
    }

    /**
     * 获取accessToken对象
     *
     * @param requestParam
     * @return 响应对象
     * @throws RequestException 请求错误
     */
    public TokenResponse getAccessToken(TokenRequestParam requestParam) throws RequestException, UnsupportedEncodingException {
        requestParam.setClientId(this.clientId);
        requestParam.setClientSecret(this.clientSecret);
        requestParam.setRedirectUri(URLEncoder.encode(this.getRedirectUri(), "utf-8"));
        StringBuilder builder = new StringBuilder(QQApiUrl.TOKEN);
        builder.append(ObjectToURIParam.toURIParam(requestParam));
        String jsonString = sendRequest(builder.toString());
        TokenResponse tokenResponse = JSON.parseObject(jsonString, TokenResponse.class);
        return tokenResponse;
    }

    /**
     * 通过accessToken过openid
     * @param accessToken
     * @return openid对象
     * @throws RequestException 请求错误
     */
    public OpenIdResponse getUserOpenId(String accessToken) throws RequestException {
        OpenIdRequestsParam openIdRequestsParam = new OpenIdRequestsParam();
        openIdRequestsParam.setAccessToken(accessToken);
        StringBuilder builder = new StringBuilder(QQApiUrl.ME);
         builder.append(ObjectToURIParam.toURIParam(openIdRequestsParam));
        String jsonString = sendRequest(builder.toString());
        return JSON.parseObject(jsonString, OpenIdResponse.class);
    }

    /**
     * 获取用户openId
     * @param requestParam AccessToken请求参数
     * @return
     * @throws UnsupportedEncodingException
     * @throws RequestException
     */
    public OpenIdResponse getUserOpenId(TokenRequestParam requestParam) throws UnsupportedEncodingException, RequestException {
        TokenResponse accessToken = this.getAccessToken(requestParam);
        OpenIdResponse userOpenId = getUserOpenId(accessToken.getAccessToken());
        return userOpenId;
    }

    /**
     * 获取用户信息
     * @param requestParam 公共参数
     * @return
     * @throws RequestException 请求错误
     */
    public UserInfoResponse getQQUserInfo(OAuthPublicParam requestParam) throws RequestException {
        StringBuilder builder = new StringBuilder(QQApiUrl.GETUSERINFO);
        builder.append(ObjectToURIParam.toURIParam(requestParam));
        String jsonString = sendRequest(builder.toString());
        UserInfoResponse userInfoResponse = JSON.parseObject(jsonString, UserInfoResponse.class);
        return userInfoResponse;
    }

    /**
     * 发送get请求
     *
     * @param requestUrl
     * @return 响应对象
     * @throws RequestException 请求错误
     */
    private String sendRequest(String requestUrl) throws RequestException {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(requestUrl).build();
        String jsonString;
        try {
            Response response = client.newCall(request).execute();
            jsonString = response.body().string();
        } catch (IOException e) {
            throw new RequestException(requestUrl + "request error", e);
        }
        return jsonString;
    }


}
